#include "RemoteHandle.h"
#include <cstring>
#include <filesystem>

std::mutex waitGetReady;
static std::atomic<int> fileTransferPart=0;

RemoteHandle::RemoteHandle(Client* evtHandler) :
    _evtHandler(evtHandler)
{
}

RemoteHandle::~RemoteHandle()
{
    threadExitFlag.store(true,std::memory_order_relaxed);
    condSendReady.notify_all();
}

void RemoteHandle::SetSocket(std::shared_ptr<oatpp::websocket::WebSocket>& socket)
{
    socketPtr=socket;
}

void RemoteHandle::AcceptData(const char* aFrame,long size)
{
    int32_t messageType;
    std::memcpy(&messageType,aFrame,sizeof(int32_t));
    if(messageType==0x3)
    {
        int32_t commandType;
        std::memcpy(&commandType,aFrame+sizeof(int32_t),sizeof(int32_t));
        switch (commandType)
        {
        case 0x1:
        //开始推流
            sendImageFlag.store(true);
            break;
        case 0x2:
        //停止推流
            sendImageFlag.store(false);
            break;
        case 0x3:
        //获取设备信息
            _evtHandler->GetDeviceStatus();
            break;
        case 0x4:
        //初始化设备
            _evtHandler->InitDevice();
            break;
        case 0x5:
        //开始拍摄
            _evtHandler->StartShot();
            break;
        case 0x6:
        //开始采集
            _evtHandler->StartSave();
            break;
        case 0x7:
        //停止拍摄
            _evtHandler->StopShot();
            break;
        case 0x8:
        //停止采集
            _evtHandler->StopSave();
            break;
        case 0x9:
        //获取相机参数
            _evtHandler->GetCameraParameter();
            break;
        case 0x10:
        //开始触发
            _evtHandler->StartTrigger();
            break;
        case 0x11:
        //取消触发
            _evtHandler->StopTrigger();
            break;
        default:
            break;
        }
    }
    else if(messageType==0x8)
    {
        int32_t commandType;
        std::memcpy(&commandType,aFrame+sizeof(int32_t),sizeof(int32_t));
        switch (commandType)
        {
        case 0x1:
        //设置图像宽度
            if(size==sizeof(int32_t)*3)
            {
                int32_t value;
                std::memcpy(&value,aFrame+sizeof(int32_t)*2,sizeof(int32_t));
                _evtHandler->SetImageWidth(value);
            }
            break;
        case 0x2:
        //设置图像高度
            if(size==sizeof(int32_t)*3)
            {
                int32_t value;
                std::memcpy(&value,aFrame+sizeof(int32_t)*2,sizeof(int32_t));
                _evtHandler->SetImageHeight(value);
            }
            break;
        case 0x3:
        //设置图像X偏移
            if(size==sizeof(int32_t)*3)
            {
                int32_t value;
                std::memcpy(&value,aFrame+sizeof(int32_t)*2,sizeof(int32_t));
                _evtHandler->SetImageOffsetX(value);
            }
            break;
        case 0x4:
        //设置图像Y偏移
            if(size==sizeof(int32_t)*3)
            {
                int32_t value;
                std::memcpy(&value,aFrame+sizeof(int32_t)*2,sizeof(int32_t));
                _evtHandler->SetImageOffsetY(value);
            }
            break;
        case 0x5:
        //设置曝光时间
            if(size==sizeof(int32_t)*3)
            {
                int32_t value;
                std::memcpy(&value,aFrame+sizeof(int32_t)*2,sizeof(int32_t));
                _evtHandler->SetExposureTime(value);
            }
            break;
        case 0x6:
        //设置帧率
            if(size==sizeof(int32_t)*3)
            {
                int32_t value;
                std::memcpy(&value,aFrame+sizeof(int32_t)*2,sizeof(int32_t));
                _evtHandler->SetFrameRate(value);
            }
            break;
        default:
            break;
        }
    }
    else if(messageType==0x9)
    {
        int32_t message;
        std::memcpy((char*)&message,aFrame+sizeof(int32_t),sizeof(int32_t));
        switch (message)
        {
        case 0x2: //请求文件传输
            _evtHandler->FileTranslate();
            break;
        case 0x3: //文件开始传输
            {
                std::lock_guard lck(FileDataMutex);
                fileTransferFlag=true;
                fileDataReady=true;
                if(fileTransferPart.load()==1)
                {
                    _evtHandler->FileTranslate();
                }
                else
                    condFileDataReady.notify_one();
            }
            break;
        case 0x4:  //文件停止传输
            {
                std::lock_guard lck(FileDataMutex);
                fileTransferFlag=false;
                fileDataReady=true;
                condFileDataReady.notify_one();
            }
            break;
        default:
            break;
        }
    }
}

std::string RemoteHandle::SendData()
{
    std::unique_lock lck(sendDataMut);
    condSendReady.wait(lck,[this]{return fileTransferEnable || sendDataFlag.load(std::memory_order_relaxed) || sendCommandFlag.load(std::memory_order_relaxed) || threadExitFlag.load(std::memory_order_relaxed);});
    if(threadExitFlag.load(std::memory_order_relaxed)) throw std::exception();
    if(sendCommandFlag.load(std::memory_order_relaxed))  //控制指令相关数据优先发送
    {
        std::lock_guard llk(sendCommandMut);
        sendCommandFlag.store(false,std::memory_order_relaxed);
        return sendCommand;
    }
    if(sendDataFlag.load(std::memory_order_relaxed))
    {
        std::lock_guard llk(sendImageMut);
        sendDataFlag.store(false,std::memory_order_relaxed);
        return sendData;
    }
    return std::string();
}

void RemoteHandle::closeTask()
{
    threadExitFlag.store(true,std::memory_order_relaxed);
    condSendReady.notify_all();
}

void RemoteHandle::StartSocket()
{
}

void RemoteHandle::SetCameraContrlHandler(Client* evtHandler)
{
    _cameraContralHandler=evtHandler;
}

static const int32_t imageTypeMask=0x1;

void RemoteHandle::SetImage(unsigned char* image,const int32_t height,const int32_t width,const pixelFormat imgFormat)
{
    if(!sendImageFlag.load(std::memory_order_relaxed)) return;  //判断是否要发送图像数据
    std::unique_lock lck(sendImageMut,std::defer_lock);
    if(lck.try_lock())  //性能优先
    {
        sendData.clear();
        int32_t sendImageDataBuffer[4]={imageTypeMask,width,height,(int32_t)imgFormat};
        sendData.append((char*)&sendImageDataBuffer,sizeof(sendImageDataBuffer));
        sendData.append((char*)image,width*height);
        sendDataFlag.store(true,std::memory_order_relaxed);
        lck.unlock();
        condSendReady.notify_one();
    }
}

static const int32_t returnValueTag=0x6;
void RemoteHandle::SendDeviceStatus(int32_t value)
{
    {
        std::lock_guard lck(sendCommandMut);
        sendCommand.clear();
        sendCommand.append((char*)&returnValueTag,sizeof(int32_t));
        sendCommand.append((char*)&value,sizeof(int32_t));
        sendCommandFlag.store(true,std::memory_order_relaxed);
    }
    condSendReady.notify_one();
}

static const int32_t cameraParaTag=0x7;
void RemoteHandle::SendCameraPara(CameraParament cameraParament)
{
    {
        std::lock_guard lck(sendCommandMut);
        sendCommand.clear();
        sendCommand.append((char*)&cameraParaTag,sizeof(int32_t));
        sendCommand.append((char*)&cameraParament,sizeof(CameraParament));
        sendCommandFlag.store(true,std::memory_order_relaxed);
    }
    condSendReady.notify_one();
}

static const int32_t messageTag=0x2;
void RemoteHandle::SendMessage(const std::string& msg)
{
    {
        std::lock_guard lck(sendCommandMut);
        sendCommand.clear();
        sendCommand.append((char*)&messageTag,sizeof(int32_t));
        sendCommand.append(msg);
        sendCommandFlag.store(true,std::memory_order_relaxed);
    }
    condSendReady.notify_one();
}


static const int32_t fileTransferTag=0x9;
void RemoteHandle::SendFileTransferCommand(const int32_t& value)
{
    {
        std::lock_guard lck(sendCommandMut);
        sendCommand.clear();
        sendCommand.append((char*)&messageTag,sizeof(int32_t));
        sendCommand.append((char*)&value,sizeof(int32_t));
        sendCommandFlag.store(true,std::memory_order_relaxed);
    }
    condSendReady.notify_one();
}

void RemoteHandle::SendFileTransferCommand(const char* value,size_t size)
{
    {
        std::lock_guard lck(sendCommandMut);
        sendCommand.clear();
        sendCommand.append((char*)&fileTransferTag,sizeof(int32_t));
        sendCommand.append(value,size);
        sendCommandFlag.store(true,std::memory_order_relaxed);
    }
    condSendReady.notify_one();
}

void RemoteHandle::GetFileTransferCommand()
{
    std::unique_lock lck(FileDataMutex);
    fileDataReady=false;
    condFileDataReady.wait(lck,[this]{return fileDataReady.load();});
    fileDataReady=false;
}

void RemoteHandle::SendAndGetFileTransferCommand(const char* value,size_t size)
{
    std::unique_lock lckA(FileDataMutex);
    fileDataReady=false;
    {
        std::lock_guard lck(sendCommandMut);
        sendCommand.clear();
        sendCommand.append((char*)&fileTransferTag,sizeof(int32_t));
        sendCommand.append(value,size);
        sendCommandFlag.store(true,std::memory_order_relaxed);
    }
    condSendReady.notify_one();
    condFileDataReady.wait(lckA,[this]{return fileDataReady.load();});
}


static std::string transferFilePath;  //保存发送的文件，在成功后文件删除
void RemoteHandle::FileTransfer(const std::string& filePath)
{
    if(fileTransferPart==0)
    {
        fileTransferPart.store(1);
        iFile.open(filePath,std::ios_base::binary);
        if(!iFile.is_open())
        {
            StopFileTransfer();
            return;
        }
        long fileSize=std::filesystem::file_size(filePath);
        allFrameCount=(fileSize+511)/512;
        struct {int32_t a;int32_t b;int64_t c;} SendSuccessMsg;
        SendSuccessMsg={0x1,0x1,allFrameCount};
        SendFileTransferCommand(reinterpret_cast<char*>(&SendSuccessMsg),sizeof(SendSuccessMsg));
    }
    else
    {
        if(!fileTransferFlag.load())
        {
            fileTransferPart.store(0);
            return;
        }
        {
            std::lock_guard lck(sendDataMut);
            fileTransferEnable=true;
        }
        transferFilePath=filePath;
        condSendReady.notify_one(); //使能数据发送
        fileTransferPart.store(0);
    }
    return;
}

bool RemoteHandle::FileTransferFuncEnable()
{
    return fileTransferEnable;
}


const int32_t sendOneBlockTag=0x5;
void RemoteHandle::SendFileData(const std::shared_ptr<oatpp::websocket::WebSocket>& socket)
{
    if(!iFile.is_open())
    {
        SendFileTransferCommand(0x4);
        fileTransferEnable=false;
        return;
    }
    OATPP_LOGI("FileTranslate","Start FileTranslate");
    std::string sendData;
    sendData.resize(512+sizeof(int32_t)*4);
    char* sendPtr=sendData.data();
    for(int64_t i=0;i<allFrameCount;i++)
    {
        if(!fileTransferFlag.load())
        {
            SendFileTransferCommand(0x4);
            fileTransferEnable=false;
            return;
        }
        std::memcpy(sendPtr,(char*)&fileTransferTag,sizeof(int32_t));
        std::memcpy(sendPtr+sizeof(int32_t),(char*)&sendOneBlockTag,sizeof(int32_t));
        std::memcpy(sendPtr+sizeof(int32_t)*2,(char*)&i,sizeof(int64_t));
        iFile.read(sendPtr+sizeof(int32_t)*4,512);
        socket->sendOneFrameBinary(sendData);
    }
    fileTransferEnable=false;
    OATPP_LOGI("FileTranslate","FileTranslate Finish");
    iFile.close();
    std::filesystem::remove(transferFilePath); //删除文件
}

void RemoteHandle::StopFileTransfer()
{
    int32_t sendMsg[2]={0x1,0x0};
    SendFileTransferCommand(reinterpret_cast<char*>(sendMsg),sizeof(int32_t)*2);
}
